/**
*FileContentManager is a Java based file manager desktop application, 
*it can show, edit and manipulate the content of the files archived inside a zip.
*
*Copyright (C) 2007 
*
*Created by Camila Sanchez [http://mimix.wordpress.com/], Rafael Naufal [http://rnaufal.livejournal.com] and Rodrigo [rdomartins@gmail.com]
*
*FileContentManager is free software; you can redistribute it and/or
*modify it under the terms of the GNU Lesser General Public
*License as published by the Free Software Foundation; either
*version 2.1 of the License, or (at your option) any later version.
*
*This library is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*Lesser General Public License for more details.
*
*You should have received a copy of the GNU Lesser General Public
*License along with FileContentManager; if not, write to the Free Software
*Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
 * Created on 22/05/2007 21:21:46
 */
package br.com.jteam.jfcm.model;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * <p>
 * Classe que representa um arquivo que pode ser visualiz&aacute;vel no modelo
 * OO.
 * 
 * @author Rafael Naufal <rafael.naufal@gmail.com>
 * @since 1.0
 * @version $Id$
 */
public class File implements Iterable<File>
{
	/**
	 * <p>
	 * Nome do arquivo.
	 */
	protected final String name;

	/**
	 * <p>
	 * Caminho do arquivo.
	 */
	protected final String path;

	/**
	 * <p>
	 * Lista de arquivos contidos no arquivo zip;
	 */
	protected List<File> files;

	/**
	 * <p>
	 * Construtor da classe <code>File</code>.
	 * 
	 * @param name -
	 *            Nome do arquivo.
	 * @param path -
	 *            Caminho do arquivo
	 * @throws Pode
	 *             lan&ccedil;ar IllegalArgumentException caso o nome ou o
	 *             caminho do arquivo seja nulo.
	 */
	public File(String name, String path)
	{
		if (name == null)
		{
			throw new IllegalArgumentException("File name cannot be null");
		}
		if (path == null)
		{
			throw new IllegalArgumentException("File path cannot be null");
		}
		this.name = name;
		this.path = path;
		files = new LinkedList<File>();
	}

	/**
	 * <p>
	 * Retorna o nome do arquivo.
	 * 
	 * @return nome do arquivo
	 */
	public String getName()
	{
		return name;
	}

	/**
	 * <p>
	 * Retorna o caminho do arquivo.
	 * 
	 * @return caminho do arquivo
	 */
	public String getPath()
	{
		return path;
	}

	/**
	 * <p>
	 * Adi&ccedil;&atilde;o de um arquivo na lista de arquivos.
	 * 
	 * @param file
	 *            arquivo a ser adicionado na lista de arquivos. Caso este
	 *            arquivo seja nulo, nada &eacute; feito.
	 * @throws UnsupportedOperationException
	 *             caso a opera&ccedil;&atilde;o <code>add</code> n&atilde;o
	 *             seja suportada por este arquivo.
	 */
	public void add(File file)
	{
		if (file != null)
		{
			files.add(file);
		}
	}

	/**
	 * <p>
	 * Remo&ccedil;&atilde;o de um arquivo da lista de arquivos.
	 * 
	 * @param file
	 *            arquivo a ser removido da lista de arquivos. Caso este arquivo
	 *            seja nulo, nada &eacute; feito.
	 * @throws UnsupportedOperationException
	 *             caso a opera&ccedil;&atilde;o <code>remove</code>
	 *             n&atilde;o seja suportada por este arquivo.
	 */
	public void remove(File file)
	{
		if (file != null)
		{
			files.remove(file);
		}
	}

	/**
	 * 
	 * <p>
	 * Obten&ccedil;&atilde;o de um arquivo da lista de arquivos.
	 * 
	 * @param index
	 *            arquivo a ser obtido na lista de arquivos. Caso este
	 *            &iacute;ndice seja menor que zero ou maior que o tamanho
	 *            corrente da lista de arquivos, retorna <code>null</code>.
	 * @throws UnsupportedOperationException
	 *             caso a opera&ccedil;&atilde;o <code>get</code> n&atilde;o
	 *             seja suportada por este arquivo.
	 */
	public File get(int index)
	{
		if (index >= 0 && index < files.size())
		{
			files.get(index);
		}
		return null;
	}

	/**
	 * <p>
	 * Produz um <code>iterator</code> da lista de arquivos corrente. 
	 * 
	 * @return iterator da lista criado.
	 * 
	 * @throws UnsupportedOperationException
	 *             caso a opera&ccedil;&atilde;o <code>iterator</code>
	 *             n&atilde;o seja suportada por este arquivo.
	 */
	public Iterator<File> iterator()
	{
		List<File> unmodifiableFiles = Collections.unmodifiableList(files);
		return unmodifiableFiles.listIterator();
	}

	/**
	 * <p>Compara inst&acirc;ncias da classe <code>File</code> para validar se s&atilde;o iguais com rela&ccedil;&atilde;o ao conte&uacute;do.
	 * @return <code>true</code> se forem iguais, <code>false</code> em caso contr&aacute;rio.
	 */
	@Override
	public boolean equals(Object other)
	{
		if (other == this)
		{
			return true;
		}
		if (other == null)
		{
			return false;
		}
		if (this.getClass() != other.getClass())
		{
			return false;
		}
		File file = (File) other;
		return ((this.getName() == file.getName())
						|| (this.getName() != null && this	.getName()
															.equals(file.getName()))
						&& (this.getPath() == file.getPath()) || (this.getPath() != null && this.getPath()
																								.equals(file.getPath())));
	}

	/**
	 * <p>Fun&ccedil;&atilde;o hash de inst&acirc;ncias da classe <code>File</code>.
	 * @return valor da fun&ccedil;&atilde;o hash.
	 */
	@Override
	public int hashCode()
	{
		int result = 17;
		if (getName() != null)
		{
			result = result * 37 + getName().hashCode();
		}
		if (getPath() != null)
		{
			result = result * 37 + getPath().hashCode();
		}
		return result;
	}

	/**
	 * <p>
	 * Produz uma String que representa visualmente o arquivo.
	 */
	@Override
	public String toString()
	{
		StringBuilder fileDescription = new StringBuilder();
		fileDescription.append("File:");
		fileDescription.append(" ");
		fileDescription.append("[");
		fileDescription.append("Name:");
		fileDescription.append(" ");
		fileDescription.append(name);
		fileDescription.append(",");
		fileDescription.append(" ");
		fileDescription.append(path);
		fileDescription.append(" ");
		fileDescription.append("]");
		return fileDescription.toString();
	}
}
